/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package naivebayes;

import java.util.List;

/**
 *
 * @author jaime
 */
public class AverageConfusionMatrix {
    
    private double averageTruePositives;
    private double averageFalsePositives;
    private double averageTrueNegatives;
    private double averageFalseNegatives;
    
    
    private double SDTruePositives;
    private double SDFalsePositives;
    private double SDTrueNegatives;
    private double SDFalseNegatives;    
    
    public AverageConfusionMatrix(List<ConfusionMatrix> matrices)
    {
        int tp[] = new int[matrices.size()];
        int fp[] = new int[matrices.size()];
        int tn[] = new int[matrices.size()];
        int fn[] = new int[matrices.size()];
        
        int i = 0;
        
        for(ConfusionMatrix cm:matrices)
        {
            tp[i] = cm.getTruePositives();
            fp[i] = cm.getFalsePositives();
            tn[i] = cm.getTrueNegatives();
            fn[i] = cm.getFalseNegatives();
                    
            i++;                    
        }
        
        averageTruePositives = average(tp);
        averageFalsePositives = average(fp);
        averageTrueNegatives = average(tn);
        averageFalseNegatives = average(fn);
        
        SDTruePositives = standardDeviation(tp, averageTruePositives);
        SDFalsePositives = standardDeviation(fp, averageFalsePositives);
        SDTrueNegatives = standardDeviation(tn, averageTrueNegatives);
        SDFalseNegatives = standardDeviation(fn, averageFalseNegatives);
        
    }
    
    private static double average(int[] values)
    {
        double average = 0;
        
        for(int v:values)
        {
            average += v;
        }
        
        average /= values.length;
        
        return average;
    }
    
    private static double standardDeviation(int[] values, double average)
    {
        double stddev = 0;
        
        for(int v:values)
        {
            stddev = (v - average)*(v - average);
        }
        
        stddev /= values.length;
        
        stddev = Math.sqrt(stddev);
        
        return stddev;
        
    }
    
    
    public double getPrecision()
    {
        return averageTruePositives*1.0/(averageTruePositives+averageFalsePositives);
    }
    
    public double getRecall()
    {
        return averageTruePositives*1.0/(averageTruePositives+averageFalseNegatives);
    }
    
    public double getFalsePositivesRate()
    {
        return averageFalsePositives*1.0/(averageFalsePositives+averageTrueNegatives);
    }
    
    //public static LearningAnalyzer 
    
    public double getFMeasure()
    {
        double precision = getPrecision();
        double recall = getRecall();
        
        return (2*precision*recall)/(precision+recall);
        
    }
    
    public String toString()
    {
        return confusionMatrixToString()+"\nPrecision = "+getPrecision()+
                "\nTVP (recall) = "+getRecall()+"\nTFP = "+getFalsePositivesRate()+
                "\nF-Measure = "+getFMeasure();
    }

    public String confusionMatrixToString() {
        String matrix = "Average matrix:\n";
        matrix += "                predicted class\n               | P | N\n";
        matrix += "real class | P | "+averageTruePositives +" | "+averageFalseNegatives+"\n"+"           | N | "+averageFalsePositives+" | "+averageTrueNegatives+"\n\n";
        
        matrix += "Standard deviation matrix:\n";
        matrix += "                predicted class\n               | P | N\n";
        matrix += "real class | P | "+SDTruePositives +" | "+SDFalseNegatives+"\n"+"           | N | "+SDFalsePositives+" | "+SDTrueNegatives+"\n";
        
        return matrix;
    }
}
